/* -------------------------------------------------------------------------- */
/*                                                                            */
/* Version: 3.1.0                                                             */
/* Date:    2023-06-14                                                        */
/* Author:  H.J. Wisselink                                                    */
/* Licence: CC by-nc-sa 4.0 ( creativecommons.org/licenses/by-nc-sa/4.0 )     */
/* Email = 'h_j_wisselink*alumnus_utwente_nl';                                */
/* Real_email = regexprep(Email,{'*','_'},{'@','.'})                          */
/*                                                                            */
/* -------------------------------------------------------------------------- */
/*                                                                            */
/* This file contains the main interface code between the SQLite3 C project   */
/* code and MATLAB/Octave.                                                    */
/* The original file by Robin Martinjak has been edited to let it conform to  */
/* the stricter standards of older compilers. It should now adhere to the     */
/* ANSI C standard and be compatible with all supported MATLAB compilers      */
/* (except the 32-bit LCC, which are missing required integer support).       */
/* While actual additional error handling has not been added, the granularity */
/* of the reported error has been improved by including the description from  */
/* the SQLite3 project file.                                                  */
/*                                                                            */
/* This mex file has also been adapted to return the version number if called */
/* with no inputs and one output.                                             */
/*                                                                            */
/* Naming rules for columns in SQLite are much more lenient than fielnames in */
/* MATLAB. To allow external handling of invalid fieldnames, the actual names */
/* are returned as a second output argument in a cell vector.                 */
/*                                                                            */
/* -------------------------------------------------------------------------- */
/*                                                                            */
/* Original file (MIT license):                                               */
/* http://web.archive.org/web/202108id_/https://raw.githubusercontent.com/    */
/* rmartinjak/mex-sqlite3/master/sqlite3.c                                    */
/*                                                                            */
/* -------------------------------------------------------------------------- */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include "sqlite3.h"
#include "mex.h"

#include "structlist_strict.h"
#include "CharConversions.c"

mxClassID dummy;

int bind_string(sqlite3_stmt *stmt, int index, const mxArray *array)
{
    int res;
    char *s;
   
    //mexPrintf("sqlite3:liang  %s:%s\n", array,"bind_string");
    s = WRAPPERmxArrayToUTF8String(array);
    res = sqlite3_bind_text(stmt, index, s,
            -1,  /* ALL the bytes */
            SQLITE_TRANSIENT  /* make a copy */
            );
    free(s);
    return res;
}

int bind_double(sqlite3_stmt *stmt, int index, const mxArray *array)
{
    int res;
    double val;
    mxClassID cls;

     int s = mxGetNumberOfElements(array);
     cls = mxGetClassID(array);
    #define GET_REALVALUE(CLASS, TYPE)  do{\
    if (cls == CLASS) { \
    TYPE *p = mxGetPr(array);\
    if(s ==1){\
         val = *p;\
         return sqlite3_bind_double(stmt, index, val);\
    }\
    else{\
        return sqlite3_bind_blob(stmt, index, (void *)p, s * sizeof(TYPE),NULL);\
    }}}  while(0)
    
    GET_REALVALUE(mxDOUBLE_CLASS, double); 
     
    GET_REALVALUE(mxSINGLE_CLASS, float); 

}

 
int bind_mxINT64_CLASS(sqlite3_stmt *stmt, int index, const mxArray *array)
{
    int res;
    mxClassID cls;
    int64_t val = 0;
    int64_t * p;
    cls = mxGetClassID(array);
    int s = mxGetNumberOfElements(array);
    p = (int64_t *)mxGetData(array);  
    if(s ==1){ 
      val = *p; 
      return sqlite3_bind_int64(stmt, index, val); 
    } 
    else {
       return sqlite3_bind_blob(stmt, index, (void *)p, s * sizeof(mxLogical),NULL); 
    }
}
int bind_mxUINT64_CLASS(sqlite3_stmt *stmt, int index, const mxArray *array)
{
    int res;
    mxClassID cls;
    int64_t val = 0;
    uint64_t * p;
    cls = mxGetClassID(array);
    int s = mxGetNumberOfElements(array);
    p = (uint64_t *)mxGetData(array);  
    if(s ==1){ 
      val = *p; 
      return sqlite3_bind_int64(stmt, index, val); 
    } 
    else {
       return sqlite3_bind_blob(stmt, index, (void *)p, s * sizeof(mxLogical),NULL); 
    }
}
int bind_mxUINT32_CLASS(sqlite3_stmt *stmt, int index, const mxArray *array)
{
    int res;
    mxClassID cls;
    int64_t val = 0;
    uint32_t * p;
    cls = mxGetClassID(array);
    int s = mxGetNumberOfElements(array);
    p = (uint32_t *)mxGetData(array);  
    if(s ==1){ 
      val = *p; 
      return sqlite3_bind_int64(stmt, index, val); 
    } 
    else {
       return sqlite3_bind_blob(stmt, index, (void *)p, s * sizeof(mxLogical),NULL); 
    }
}
int bind_mxINT32_CLASS(sqlite3_stmt *stmt, int index, const mxArray *array)
{
    int res;
    mxClassID cls;
    int64_t val = 0;
    int32_t * p;
    cls = mxGetClassID(array);
    int s = mxGetNumberOfElements(array);
    p = (int32_t *)mxGetData(array);  
    if(s ==1){ 
      val = *p; 
      return sqlite3_bind_int64(stmt, index, val); 
    } 
    else {
       return sqlite3_bind_blob(stmt, index, (void *)p, s * sizeof(mxLogical),NULL); 
    }
}
int bind_mxUINT16_CLASS(sqlite3_stmt *stmt, int index, const mxArray *array)
{
    int res;
    mxClassID cls;
    int64_t val = 0;
    uint16_t * p;
    cls = mxGetClassID(array);
    int s = mxGetNumberOfElements(array);
    p = (uint16_t *)mxGetData(array);  
    if(s ==1){ 
      val = *p; 
      return sqlite3_bind_int64(stmt, index, val); 
    } 
    else {
       return sqlite3_bind_blob(stmt, index, (void *)p, s * sizeof(mxLogical),NULL); 
    }
}
int bind_mxINT16_CLASS(sqlite3_stmt *stmt, int index, const mxArray *array)
{
    int res;
    mxClassID cls;
    int64_t val = 0;
    int16_t * p;
    cls = mxGetClassID(array);
    int s = mxGetNumberOfElements(array);
    p = (int16_t *)mxGetData(array);  
    if(s ==1){ 
      val = *p; 
      return sqlite3_bind_int64(stmt, index, val); 
    } 
    else {
       return sqlite3_bind_blob(stmt, index, (void *)p, s * sizeof(mxLogical),NULL); 
    }
}

int bind_mxINT8_CLASS(sqlite3_stmt *stmt, int index, const mxArray *array)
{
    int res;
    mxClassID cls;
    int64_t val = 0;
    int8_t * p;
    cls = mxGetClassID(array);
    int s = mxGetNumberOfElements(array);
    p = (int8_t *)mxGetData(array);  
    if(s ==1){ 
      val = *p; 
      return sqlite3_bind_int64(stmt, index, val); 
    } 
    else {
       return sqlite3_bind_blob(stmt, index, (void *)p, s * sizeof(mxLogical),NULL); 
    }
}
int bind_mxUINT8_CLASS(sqlite3_stmt *stmt, int index, const mxArray *array)
{
    int res;
    mxClassID cls;
    int64_t val = 0;
    uint8_t * p;
    cls = mxGetClassID(array);
    int s = mxGetNumberOfElements(array);
    p = (uint8_t *)mxGetData(array);  
    if(s ==1){ 
      val = *p; 
      return sqlite3_bind_int64(stmt, index, val); 
    } 
    else {
       return sqlite3_bind_blob(stmt, index, (void *)p, s * sizeof(mxLogical),NULL); 
    }
}
int bind_mxLOGICAL_CLASS(sqlite3_stmt *stmt, int index, const mxArray *array)
{
    int res;
    mxClassID cls;
    int64_t val = 0;
    mxLogical * p;
    cls = mxGetClassID(array);
    int s = mxGetNumberOfElements(array);
    p = (mxLogical *)mxGetData(array);  
    if(s ==1){ 
      val = *p; 
      return sqlite3_bind_int64(stmt, index, val); 
    } 
    else {
       return sqlite3_bind_blob(stmt, index, (void *)p, s * sizeof(mxLogical),NULL); 
    }
}

int bind_params(sqlite3_stmt* stmt, const mxArray *params, int column)
{
    int res, i, n = mxGetNumberOfFields(params);
  
    if (mxGetClassID(params) != mxSTRUCT_CLASS) {
        return res;
    }
 
          
    for (i = 0; i < n; i++) {//column
        mxArray *array = mxGetFieldByNumber(params, column, i);
        mxClassID cls = mxGetClassID(array);
 
            int sizeofClass= mxGetElementSize(array);
        int res;
        switch (cls) {
            case  mxFUNCTION_CLASS:
            case  mxCELL_CLASS:
            case  mxSTRUCT_CLASS:    
            case  mxUNKNOWN_CLASS:
                mexPrintf(" column  %d = NULL ; \n", i);
                break;
            case mxINT8_CLASS  : res = bind_mxINT8_CLASS (stmt, i + 1, array); break;
            case mxUINT8_CLASS :  res =bind_mxUINT8_CLASS(stmt, i + 1, array); break;
            case mxINT16_CLASS :  res =bind_mxINT16_CLASS(stmt, i + 1, array); break;
            case mxUINT16_CLASS:  res =bind_mxUINT16_CLASS(stmt, i + 1, array); break;
            case mxINT32_CLASS :  res =bind_mxINT32_CLASS(stmt, i + 1, array); break;
            case mxUINT32_CLASS:  res =bind_mxUINT32_CLASS(stmt, i + 1, array); break;
            case mxINT64_CLASS : res = bind_mxINT64_CLASS(stmt, i + 1, array); break;
            case mxUINT64_CLASS:  res =bind_mxUINT64_CLASS(stmt, i + 1, array); break;
            case mxCHAR_CLASS: res = bind_string(stmt, i + 1, array); break;
            case mxSINGLE_CLASS:
            case mxDOUBLE_CLASS:
                res = bind_double(stmt, i + 1, array);
                break;
            default:  ;
        }
        if (res != SQLITE_OK) {
            return res;
        }
    }
    return SQLITE_OK;
}

int execute_many(sqlite3 *db, sqlite3_stmt *stmt, const mxArray *params)
{
    int res, i, n = mxGetN(params);
     
    for (i = 0; i < n; i++) {//rows
        res = bind_params(stmt, params, i);
        if (res != SQLITE_OK) {
            return res;
        }

        res = sqlite3_step(stmt);
        if (res != SQLITE_DONE) {
            return res;
        }
        sqlite3_reset(stmt);
        sqlite3_clear_bindings(stmt);
    }
    return SQLITE_DONE;
}


mxArray *get_column(sqlite3_stmt *stmt, int index)
{
    int type = sqlite3_column_type(stmt, index);
    if (type == SQLITE_TEXT) {
        const char *text = sqlite3_column_text(stmt, index);
        if(text[0]==0){
           //return mxCreateDoubleScalar(mxGetNaN());
           return mxCreateCharMatrixFromStrings(1,&text);
        }
        return WRAPPERmxCreateCharMatrixFromStrings(1, &text);
      
    } else if (type == SQLITE_FLOAT) {
        return mxCreateDoubleScalar(sqlite3_column_double(stmt, index));
    } else if (type == SQLITE_INTEGER) {
        mxArray *a = mxCreateNumericMatrix(1,1, mxINT64_CLASS, mxREAL);
         int64_t *p =mxCalloc(1, sizeof(int64_t));
         p[0]= sqlite3_column_int64(stmt, index);
        mxSetData(a, p);
        //memcpy(mxGetData(a), &val, sizeof val);
        return a;
    } else if (type == SQLITE_NULL) {
        /* This return a NULL as a NaN.*/
        return mxCreateDoubleScalar(mxGetNaN());
    } else if (type == SQLITE_BLOB) {
        int col_bytes= sqlite3_column_bytes(stmt, index);
        if( col_bytes==0){
			return mxCreateDoubleScalar(mxGetNaN());
		}
        mxArray *a = mxCreateNumericMatrix(1, col_bytes, mxUINT8_CLASS, mxREAL);
        uint8_t *pVal = mxCalloc(1, sizeof(uint8_t)*col_bytes);
        void *b = sqlite3_column_blob(stmt, index);
		if(b==NULL){
            
			return mxCreateDoubleScalar(mxGetNaN());
		}
		else{
            memcpy(pVal, b, col_bytes);
            mxSetData(a, pVal);
			//memcpy(mxGetData(a), b, col_bytes);
			return a;
		}
		  
        /* This returns an error later. */
       
    }
    /* This should never happen. */
    return NULL;
}

int fetch_row(sqlite3_stmt *stmt, int num_columns, mxArray **array)
{
    mxArray *data;
    int i, res = sqlite3_step(stmt); 
    if (res == SQLITE_ROW) {
        for (i = 0; i < num_columns; i++) { 
            data = get_column(stmt, i);
            if (data)
            {
                /* Write data to the mxArray. */
                mxSetFieldByNumber(*array, 0, i, mxDuplicateArray(data));//mxDuplicateArray(data)
                //mxDestroyArray(data);
            }
            else
            {
                /* Throw "Unsupported column type" error. */
                return SQLITE_FORMAT;
            }
        }
    }
    return res;
}


/* This function is not used, but could be used in fetch_results() to detect */
/* invalid field names and generate a MATLAB-compatible field name. */
int validate_field_name(const char *name)
{
    /* Check whether the field name is actually allowed in Matlab. */
    int isValid,i,currentChar;
    currentChar = name[0];
    currentChar = (int)currentChar;
    if (!((currentChar>=48 && currentChar<=57) ||
          (currentChar>=65 && currentChar<=90) ||
          (currentChar>=97 && currentChar<=122)
         )) {
        return isValid=0;
    }
    for (i = 1; i < strlen(name); i++) {
        currentChar = name[i];
        currentChar = (int)currentChar;
        if (!((currentChar>=48 && currentChar<=57) ||
              (currentChar>=65 && currentChar<=90) ||
              (currentChar>=97 && currentChar<=122) ||
              currentChar==95)) {
            return isValid=0;
        }
    }
    return isValid=1;
}

int fetch_results(sqlite3_stmt *stmt, mxArray **results, mxArray **columnnames)
{
    /* Fetch the data from the data and store the results in the first output */
    /* argument. The second output argument is used to keep track of the      */
    /* SQLite column names in case they are invalid.                          */
    mxArray *row;mxArray *nameAsmxChar;int i, num_columns, res;
    struct structlist result_list;
    structlist_init(&result_list);
    num_columns = sqlite3_column_count(stmt);
    /* Create a struct element with the correct fields. */
    row = mxCreateStructMatrix(1, 1,0, NULL);
    /* 生成列名. */
    *columnnames = mxCreateCellMatrix(num_columns, 1);
    for (i = 0; i < num_columns; i++) {
        const char *name = sqlite3_column_name(stmt, i);
        nameAsmxChar = WRAPPERmxCreateCharMatrixFromStrings(1, &name);
        mxSetCell(*columnnames, i, nameAsmxChar);
        sprintf((char *)name,"field_%d",i+1);
        mxAddField(row, (const char *)name);
    }
     time_t curtime;
 
     time(&curtime);
     mexPrintf("sqlite:all start %s\n",ctime(&curtime));
    /* 遍历 行列 */
    while (res = fetch_row(stmt, num_columns, &row),
            res == SQLITE_ROW) {
        structlist_add(&result_list, row);
    }
      time(&curtime);
     mexPrintf("sqlite:all in %s\n",ctime(&curtime));
    *results = structlist_collapse(&result_list);
      //structlist_free(&result_list);
      time(&curtime);
     mexPrintf("sqlite:all end %s\n",ctime(&curtime));
    return res;
}

#define sql_exec(cmd) if( (res=sqlite3_exec(db, cmd, 0, 0, &zErrMsg)) != SQLITE_OK ){\
							mexPrintf("SQL:%d %s\n",res, zErrMsg);\
							sqlite3_free(zErrMsg);\
						}
void
        mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    char *db_path, *query;
    sqlite3 *db;
    sqlite3_stmt *stmt;
    int res,num_columns;
    char *zErrMsg = 0;
    enum { RHS_FILENAME, RHS_QUERY, RHS_PARAMS };
    if (nlhs<2 || nrhs< 2) {
        plhs[0] = mxCreateString("ver : modify By liangsai");
        return;
    } else {
         plhs[0] = mxCreateStructMatrix(1, 1, 0, NULL);
         plhs[1] = mxCreateCellMatrix(1, 1);
    }
    
    if (nrhs < 2) {
        mexErrMsgIdAndTxt("MUST  > tow args ;  ",
                "usage: sqlite3(file, query[, params])");
    }
    
    db_path = WRAPPERmxArrayToUTF8String(prhs[RHS_FILENAME]);
    query = WRAPPERmxArrayToUTF8String(prhs[RHS_QUERY]);
 
    if (sqlite3_open(db_path, &db) != SQLITE_OK) {
        mexErrMsgIdAndTxt("sqlite3:open", "failed to open db");
    }
     //sql_exec( "PRAGMA synchronous = OFF; ")
	
	//sql_exec( "PRAGMA auto_vacuum = 0; ")
	
	//sql_exec( "PRAGMA journal_mode = OFF; ")

	//sql_exec( "PRAGMA case_sensitive_like = 1; ")

	sql_exec( "PRAGMA cache_size = 32768; ")
    
   //sql_exec( "PRAGMA mmap_size = 1*1024*1024*1024; ")
    
   // sql_exec( " PRAGMA temp_store = memory; ")
    
    
    res = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
    if (res != SQLITE_OK) {
        sqlite3_close(db);
        mexErrMsgIdAndTxt(
            "sqlite3:prepare",
            "Failed to prepare query.\n"
            "Reasons could be invalid syntax or creating a table that already exists.\n"
            "sqlite3_prepare_v2 returned status code %d",
            res);
    }
    
    num_columns = sqlite3_column_count(stmt);
    
    if (num_columns > 0) {
        /* Looks like a SELECT query */
        res = fetch_results(stmt, &plhs[0], &plhs[1]);
    } else {
        /* If the user passes a struct array, use this to execute the statement
         * for each column */
        if (nrhs > 2) {
            res = execute_many(db, stmt, prhs[RHS_PARAMS]);
        } else {
            res = sqlite3_step(stmt);
        }
    }
    
    if (res == SQLITE_DONE) {
        /* success! */
        sqlite3_finalize(stmt);
        sqlite3_close(db);
        return;
    }

    /* Close the database file before throwing an error. */
    sqlite3_close(db);

    if(res == SQLITE_ERROR)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_ERROR",
                "SQLite responded with error code %d:\n%s",
                 res,"Generic error");
    } else if(res == SQLITE_INTERNAL)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_INTERNAL",
                "SQLite responded with error code %d:\n%s",
                 res,"Internal logic error in SQLite");
    } else if(res == SQLITE_PERM)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_PERM",
                "SQLite responded with error code %d:\n%s",
                 res,"Access permission denied");
    } else if(res == SQLITE_ABORT)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_ABORT",
                "SQLite responded with error code %d:\n%s",
                 res,"Callback routine requested an abort");
    } else if(res == SQLITE_BUSY)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_BUSY",
                "SQLite responded with error code %d:\n%s",
                 res,"The database file is locked");
    } else if(res == SQLITE_LOCKED)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_LOCKED",
                "SQLite responded with error code %d:\n%s",
                 res,"A table in the database is locked");
    } else if(res == SQLITE_NOMEM)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_NOMEM",
                "SQLite responded with error code %d:\n%s",
                 res,"A malloc() failed");
    } else if(res == SQLITE_READONLY)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_READONLY",
                "SQLite responded with error code %d:\n%s",
                 res,"Attempt to write a readonly database");
    } else if(res == SQLITE_INTERRUPT)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_INTERRUPT",
                "SQLite responded with error code %d:\n%s",
                 res,"Operation terminated by sqlite3_interrupt()");
    } else if(res == SQLITE_IOERR)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_IOERR",
                "SQLite responded with error code %d:\n%s",
                 res,"Some kind of disk I/O error occurred");
    } else if(res == SQLITE_CORRUPT)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_CORRUPT",
                "SQLite responded with error code %d:\n%s",
                 res,"The database disk image is malformed");
    } else if(res == SQLITE_NOTFOUND)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_NOTFOUND",
                "SQLite responded with error code %d:\n%s",
                 res,"Unknown opcode in sqlite3_file_control()");
    } else if(res == SQLITE_FULL)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_FULL",
                "SQLite responded with error code %d:\n%s",
                 res,"Insertion failed because database is full");
    } else if(res == SQLITE_CANTOPEN)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_CANTOPEN",
                "SQLite responded with error code %d:\n%s",
                 res,"Unable to open the database file");
    } else if(res == SQLITE_PROTOCOL)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_PROTOCOL",
                "SQLite responded with error code %d:\n%s",
                 res,"Database lock protocol error");
    } else if(res == SQLITE_EMPTY)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_EMPTY",
                "SQLite responded with error code %d:\n%s",
                 res,"Internal use only");
    } else if(res == SQLITE_SCHEMA)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_SCHEMA",
                "SQLite responded with error code %d:\n%s",
                 res,"The database schema changed");
    } else if(res == SQLITE_TOOBIG)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_TOOBIG",
                "SQLite responded with error code %d:\n%s",
                 res,"String or BLOB exceeds size limit");
    } else if(res == SQLITE_CONSTRAINT)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_CONSTRAINT",
                "SQLite responded with error code %d:\n%s",
                 res,"Abort due to constraint violation");
    } else if(res == SQLITE_MISMATCH)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_MISMATCH",
                "SQLite responded with error code %d:\n%s",
                 res,"Data type mismatch");
    } else if(res == SQLITE_MISUSE)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_MISUSE",
                "SQLite responded with error code %d:\n%s",
                 res,"Library used incorrectly");
    } else if(res == SQLITE_NOLFS)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_NOLFS",
                "SQLite responded with error code %d:\n%s",
                 res,"Uses OS features not supported on host");
    } else if(res == SQLITE_AUTH)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_AUTH",
                "SQLite responded with error code %d:\n%s",
                 res,"Authorization denied");
    } else if(res == SQLITE_FORMAT)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_FORMAT",
                "SQLite responded with error code %d:\n%s",
                 res,"Unsupported column type");
    } else if(res == SQLITE_RANGE)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_RANGE",
                "SQLite responded with error code %d:\n%s",
                 res,"2nd parameter to sqlite3_bind out of range");
    } else if(res == SQLITE_NOTADB)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_NOTADB",
                "SQLite responded with error code %d:\n%s",
                 res,"File opened that is not a database file");
    } else if(res == SQLITE_NOTICE)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_NOTICE",
                "SQLite responded with error code %d:\n%s",
                 res,"Notifications from sqlite3_log()");
    } else if(res == SQLITE_WARNING)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_WARNING",
                "SQLite responded with error code %d:\n%s",
                 res,"Warnings from sqlite3_log()");
    } else if(res == SQLITE_ROW)  {
        mexErrMsgIdAndTxt("sqlite3:SQLITE_ROW",
                "SQLite responded with error code %d:\n%s",
                 res,"sqlite3_step() has another row ready");
    } else {
        mexErrMsgIdAndTxt("sqlite3:UnknownError",
                "SQLite responded with error code %d",res);
    }
}